﻿/*
-----------------------------------------------------------------------------------
<copyright file="JavaResponse.js" company="Microsoft Corporation">
         (c) © 2016 Microsoft. All rights reserved.
    
</copyright>
---------------------------------------------------------------------------------
*/

function javaResponse(result) {
    if (!result.CompilerOutput) {
        if (result.StdOut) {
            javaOutput(result);
        }

        if (result.StdErr && result.StdErr.includes("Process ended by server because the")) {
            serverTimeout(result);
        }
        else if (result.StdErr && result.StdErr.includes("Internal server error")) {
            serverError(result);
        }
        else if (result.StdErr) {
            javaRuntimeError(result);
        }
        accordionify();
    }
    else {
        var errStr = fixJavaErrors(result.CompilerOutput);
        compilerErrors = errStr;
        javaCmplErr();
    }
}

function javaOutput(result) {
    var outChars = result.StdOut.length;
    var maxOutputChars = 100000;
    var preOutput;
    if (outChars > maxOutputChars) {
        document.getElementById("consoleHeader").innerHTML = "Console - Max output";
        addErrorAccordionElement("div", "p", "errorMessage", "errorHelp",
            "Maximum output was reached", "There was too much output, " +
            "so to preserve efficiency only the last 100,000 characters " +
            "of output are being displayed. The '...' indicates output " +
            "before what is being displayed", "0", "-1", "contentExtend");
        preOutput = "...\n" + result.StdOut.substring(outChars - maxOutputChars);
    } else {
        document.getElementById("consoleHeader").innerHTML = "Console - No errors";
        preOutput = result.StdOut;
    }
    var output = preOutput.split("\n");
    addElement("div", "successMessage", "", "contentExtend", "0");
    var outputLength = output.length;
    var linesPerDiv = 1000;
    for (var i = 0; i < (outputLength / linesPerDiv) ; i++) {
        var toOutput = "";
        for (var j = 0; j < linesPerDiv; j++) {
            if ((linesPerDiv * i + j) < outputLength) {
                if (j == 0) {
                    toOutput += output[linesPerDiv * i + j];
                } else {
                    toOutput += "\n" + output[linesPerDiv * i + j];
                }
            } else {
                break;
            }
        }
        addElementByClass("div", "outputText", toOutput, "successMessage");
    }
}

function javaRuntimeError(result) {
    addErrorAccordionElement("div", "p", "errorMessage", "errorHelp", result.StdErr,
                result.RunErrInfo, "0", "-1", "contentExtend");
    document.getElementById("consoleHeader").innerHTML = ("Console - Runtime error");
}

function fixJavaErrors(errorOutput) {
    return errorOutput.replace(/: error:/g, "\nError:");
}

function javaCmplErr() {
    var errArr = compilerErrors.split("\n"),
    driveName = errArr[0].substring(0, 4);
    var numErrors = errArr[errArr.length - 1];
    errArr.pop();
    var errors = [];
    var i = 0;
    var j = 1;
    errors[0] = errArr[0] + "\n";
    while (j < errArr.length) {
        while ((j < errArr.length) && (driveName != errArr[j].substring(0, 4))) {
            errors[i] += errArr[j] + "\n";
            j++;
        }
        if (j < errArr.length) {
            i++;
            errors[i] = errArr[j] + "\n";
            j++;
        }
    }

    for (var k = 0; k < errors.length; k++) {
        addErrorAccordionElement("div", "p", "errorMessage", "errorHelp", errors[k],
            javaCmplErrInfo(errors[k]), "0", "-1", "contentExtend");
    }

    accordionify();
    document.getElementById("consoleHeader").innerHTML = ("Console - " + numErrors);
}

function javaCmplErrInfo(cmplErr) {
    var errInfo = "No info available for this error";
    if (cmplErr.includes("_J_A_V_A__S_E_C_U_R_I_T_Y_") && cmplErr.includes(".main(args)")) {
        errInfo = "You are attempting to run a file without a main method. Please add a main " +
            "method and try again. Also, check if you are using a reserved word (i.e. " +
            "int, double, etc). Note that this is not the error you would normally get if " +
            "you were missing a main method. This error is occurring due to the extra security " +
            "precautions taken."
        return errInfo;
    }

    var errArr = cmplErr.split("\n");
    var err = errArr[1];
    if (err.includes("cannot find symbol")) {
        errInfo = "This error usually occurs when a misspelled or undeclared variable is attempted to be used." +
            "This will also occur if a method was misspelled or called incorrectly. Lastly this wil occur if " +
            "you forgot to import the necessary Java package.\n\n" +
            "The line number (found at the end of the top line of the error) will tell you where the error occurred, " +
            "the symbol will tell you which variable caused the error, and the location will tell you in which class " +
            "the error occurred.\n\n" +
            "Variable issues: Find the variable that caused the error and first check the spelling. If the spelling is " +
            "correct then check where and if the variable was declared. If that is correct then check the scope " +
            "of the variable.\n\n" +
            "Method issues: Find the method that caused the error and check the spelling. If that is correct make sure " +
            "the method was declared. Then check if it was called correctly (methods must have parentheses at the end).\n\n" +
            "Missing packages: Check to make sure that the problematic class was spelled correctly. If so then ensure " +
            "the Java packages necessary for its usage are imported. For example using the Scanner class requires " +
            "importing java.util.Scanner";
    }
    else if (err.includes("is already defined in")) {
        errInfo = "This error occurs when you declare a variable of method with the same name. Find the line where the " +
            "error occurs and remove the second declaration of the variable. For example if you declare int count = 1; " +
            "and later in the code write int count = 5; then this error will occur. If you want to change the value of " +
            "count, then simply set it without putting the type again: count = 5;. A similar problem applies for methods. " +
            "Remember that methods can have the same name as long as the parameters are different. There either needs to " +
            "be a different number of parameters or a different order of the types.";
    }
    else if (err.includes("duplicate class")) {
        errInfo = "This error occurs when you declare two of the exact same class. Make sure that the classes have " +
            "different names.";
    }
    else if (err.includes("is public, should be declared in a file named")) {
        errInfo = "This error occurs when using a public class that is difference than the file name. " +
            "Make sure that the name of the file matches the name of the class exactly (including casing)";
    }
    else if (err.includes("class, interface, or enum expected")) {
        errInfo = "This error occurs when the program is expecting another class, interface, or enum to begin. " +
            "Normally it is a result of too many closing curly braces. First indent the program correctly, then " +
            "match up all the curly braces and make sure that there are no standalone curly braces. Also, make " +
            "sure that there is no code sitting outside of a class.";
    }
    else if (err.includes("<identifier> expected")) {
        errInfo = "This error occurs if code is written outside of a method when it is not allowed to be there. " +
            "Look at the lines where the error occurs and move them inside a method. You may have issues with the " +
            "placement of the curly braces. The easiest way to check for the problem is to make sure that the code " +
            "is correctly indented and then looking at the lines where the error occured and moving the lines as " +
            "necessary.\n\n" +
            "This error will also occur if you have an incorrect method heading. Check your method heading so that " +
            "it is formatted correctly: the privacy modifier, static if it is a static method, the return type, and " +
            "the method name.";
    }
    else if (err.includes("expected")) {
        errInfo = "This error occurs when the compiler detects a missing character is detected. Although the compiler " +
            "is often correct about which character is missing, you cannot guarantee that it will be right. Go to " +
            "the line where the error was detected and check if the expected character will make sense. If so, add it " +
            "in and recompile. Otherwise check what the code was intended to do and fix it as necessary.";
    }
    else if (err.includes("illegal start of expression")) {
        errInfo = "This error occurs when a line of code is written that cannot exist in that place. For example, " +
            "not closing a method before starting a new one will result in this error. Look for missing closing " +
            "parentheses, square brackets, and curly braces. Also check to see if an expression carries across " +
            "multiple lines and is not connected properly. For example, forgetting to put a concatenation symbol " +
            "between broken strings. This error may occur within a line that looks perfectly okay if you are " +
            "doing operations that are expected in certain places in a statement, but occur in the wrong places " +
            "in your code.";
    }
    else if (err.includes("possible lossy conversion")) {
        errInfo = "This error occurs when you attempt to store a value that can carry more information that the type " +
            "of the variable you are trying to assign it to. For example, trying to store a double value (like 2.1) to " +
            "an int variable (int x = 2.1). The 2.1 is a double value and therefore is able to store more information " +
            "than an int can. Although the double you are trying to assign may not be too much information, the compiler " +
            "will have an issue because it could be too much information. The found line tells you the type of information " +
            "you attempted to pass in, and the required line tells you the expected type of information. If the error " +
            "says possible lossy conversion from <typeA> to <typeB> then typeA is the found and typeB is required." +
            "Either cast the problematic value to the correct type or simply find a way to change that value that is " +
            "being passed in.";
    }
    else if (err.includes("incompatible types")) {
        errInfo = "This error occurs when trying to convert between types. Trying to set the value of an int variable " +
            "to a String will result in this error. The found line will tell you the type found where the error occurred, " +
            "and the required line will tell you the expected type. If the program says <typeA> cannot be converted to " +
            "<typeB> then typeA was found and typeB was required. Go back to the code where the error was found and " +
            "check the logic used as this is not the result of a syntax error. Make sure you know what type of " +
            "type conversions are okay and what are not. For example converting primitive types directly to objects " +
            "is not possible without the assisstance of another class or method.\n\n" +
            "This error will also occur when in an if statement you attempt use an = sign for comparison operator " +
            "instead of an ==. Remember that == will compare two values and return a boolean. = will assign the " +
            "value of the right side to the variable on the left. There are other ways to get this error within " +
            "an if statement if you attempt to use operations that do not return booleans.";
    }
    else if (err.includes("not a statement")) {
        errInfo = "This error occurs when the written code isn't valid. It is often accompanied by a ';' expected " +
            "error. Check the code to make sure that the code that is written is written in the correct java format " +
            "and doesn't have any misplaced characters (semicolon, parenthesis, etc.) that cut the statement short, " +
            "confusing the compiler about where the statement ends and a new one begins.";
    }
    else if (err.includes("return type required")) {
        errInfo = "This error occurs when no return type is specified in a method header. All Java methods require a " +
            "return type. If nothing will be returned then put void as the return type, otherwise put the return type of " +
            "what will be returned.";
    }
    else if (err.includes("cannot be applied to given types")) {
        errInfo = "This error occurs when the parameters of the method call do not match the number or types of the " +
            "parameters in the method declaration. The required line will tell you the order in which the parameters " +
            "are expected, the found line will tell you the order that the parameters were used to call the method. " +
            "To fix this simply change the types and order of the parameters to match the required parameters.";
    }
    else if (err.includes("missing return statement")) {
        errInfo = "This error occurs when you declare a method with a non-void return type, but fail to return a value " +
            "or the compiler is confused about the return statement. Go to the method where the error occurred, check " +
            "the return type, and make sure that you returned a value from the method. It is possible to get this error " +
            "if you have a valid return statement, but the compiler thinks that there is a way for the code to never " +
            "reach the statement. For example, if you have two if statements, one that returns one value if the input " +
            "number is greater than 0 and one that returns a different value if the input number is less than or equal " +
            "to 0. You know for a fact that a number has to be less than, greater than, or equal to 0, but because there " +
            "are only if statements the compiler isn't sure that the code will always return something. An easy fix " +
            "is to simply put a default return statement at the end or to remove the last if statement (you " +
            "could replace it with an else statement and the compiler would accept it).";
    }
    else if (err.includes("reached end of file while parsing")) {
        errInfo = "The error occurs when the class is not closed off and the program reads to the end of the file. " +
            "Properly indent the code and make sure that all opening curly braces match with a closing curly brace " +
            "where expected.";
    }
    else if (err.includes("unreachable statement")) {
        errInfo = "This error occurs when there is a statement that is detected to be unreachable by the compiler. This " +
            "happens normally when a statement is placed after a return, break, continue, etc. Make sure that after these " +
            "types of statements there are no others within the same block of code. Either move the problematic " +
            "statements before any statements that cut the flow of the code or find a way to change the logic of " +
            "the program so that all statements become reachable.";
    }
    else if (err.includes("might not have been initialized")) {
        errInfo = "This error occurs when the compiler sees that there is a possibility of a variable not being given " +
            "an initial value before being used in a calculation or operation. Find the variable that the compiler " +
            "says may not have been initialized. First look where it is initially declared and see if it attempted " +
            "to be used without being given a value. If it appears that there is a path for the variable to be " +
            "initialized make sure that the variable is set before it is used. The easiest way to solve this problem is to " +
            "simply give the variable some initial value and not wait to set it. If you are using if statements to decide " +
            "how to set the variable then the compiler will be confused even it seems that the program must hit an " +
            "if statements. For example if you have an if statement that checks to see if a boolean is true and one " +
            "to check if it is false (setting the variable accordingly) then the compiler will think that it is possible " +
            "to skip over the if statements and never set the variable. Either remove one of the if statements or make " +
            "the last one into an else statement.";
    }
    else if (err.includes("has private access in")) {
        errInfo = "This error occurs when you are attempting to get or set the value of a private field in a separate " +
            "class. If you want to do these operations with a private field then you must use getter/accessor or " +
            "setter/mutator methods.";
    }
    else if (err.includes("cannot be referenced from static content")) {
        errInfo = "This error occurs when you are attempting to reference a non-static method (without the static " +
            "keyword) from a static method (with the static keyword. Static methods, by definition, always exist and " +
            "can be used. Non-static methods can only be referenced when an instance of the class, which it is in, " +
            "is referenced. For example, if I create a CartesianCoordinate class (in a separate file) with a bunch " +
            "of non-static methods in it then I cannot reference any of the methods in the class unless a " +
            "CartesianCoordinate object is instantiated and I call the methods on that object. The CartesianCoordinate " +
            "object has access to the non-static methods, but the rest of the class which you are working in does not.";
    }
    else if (err.includes("cannot be referenced from a static context")) {
        errInfo = "This error occurs when you are attempting to reference a non-static variable from a static method. " +
            "Remember that non-static fields are only a part of the class in which they are defined. So if you have " +
            "'public int distance = 3' and attempt to reference that from main then you will get this error. Even if " +
            "main and the variable are in the same class, you must create an instance of that class in order to access " +
            "the non-static variable.";
    }
    else if (err.includes("package") && err.includes("does not exist")) {
        errInfo = "This error occurs when you attempt to import a package that the compiler cannot recognize or locate. " +
            "Check the spelling and casing in the package name. If they appear to be right then make sure that the " +
            "path is correct. If it is a java or related package then check the Java APIs to make sure that the package " +
            "exists there.";
    }
    else if (err.includes("bad operand types")) {
        errInfo = "This error occurs if you are attempting to use operands with types that do not work for a binary " +
            "operator. For example, attempting to use the subtraction operator with Strings or trying to use a comparison " +
            "operator (||, &&, <, >, ==, etc.) with improper types. The line that says 'first type' is the type on the left " +
            "of the operator and the second type is the type on the right of the operator. On the line that says 'Error:' " +
            "it will also say 'bad operand types for binary operator' and then an operator in single quotes. That is the " +
            "operator that the program is unable to use to complete the operation given the two types. If you can see why " +
            "the two types are wrong, then fix the types to make sure that the operator can operate on the two types. If " +
            "you cannot see the problem then it might be because you are doing multiple operations together.\n\n" +
            "For example if you try to put 'x < y < z' (assuming x, y, z are ints) in an if statement then you will get " +
            "this error and it will probably say the first type is a boolean and the second type is an int and the " +
            "binary operator is '<'. This is happening because the program first does the x < y comparison, which returns " +
            "a boolean. Then it attempts to do the second operation which is boolean < int. Instead, you must do 'x < y " +
            "&& y < z'. Now you have a boolean for x < y and a boolean for y < z. The final operation is boolean && " +
            "boolean, which is a valid operation that returns a boolean. Make sure you know what types of operands are " +
            "required for each operator.\n\n" +
            "Note: Unary operators are ones that operate on one operand and binary operators are ones that operate on " +
            "two operands.";
    }
    else if (err.includes("bad operand type")) {
        errInfo = "This error occurs when you attempt to use an operand with a unary operator that doesn't work because " +
            "the type doesn't work for the operator. For example, trying to use '!' with an int will give this error " +
            "because the '!' can only work with boolean operands. This error often occurs when you mistakenly put two " +
            "operators next to each other. For example concatenating two Strings: 'Hello ' + + 'World'. Make sure that" +
            "you have only one operator between operands and that you know which types of operands are required for " +
            "unary operators.\n\n" +
            "Note: Unary operators are ones that operate on one operand and binary operators are ones that operate on " +
            "two operands.";
    }
    else if (err.includes("illegal start of type")) {
        errInfo = "This error often occurs when your curly braces don't match. Format your code and check that the " +
            "curly braces are correct. Another issues is when code is outside of a method. Make sure that any code, " +
            "other than declarations, is within a method. All of your code should be inside a class. " +
            "This error is related to the error '<identifier> expected'.";
    }
    else if (err.includes("'else' without 'if'")) {
        errInfo = "This error occurs when you forget to put an if statement before putting an else if or an else " +
            "statement. You may have put an if statement, but due to curly brace errors or other syntax issues " +
            "the compiler may not recognize that the else statement and the if statement are connected. First " +
            "check to see if you put an if statement before your else statement. If so, then format your code and " +
            "check your curly braces to make sure that they are matched up correctly.";
    }
    else if (err.includes("illegal combination of modifiers")) {
        errInfo = "This error occurs when you have a combination of modifiers that doesn't work. Look at the modifiers " +
            "that the compiler says are an illegal combination and figure out which one needs to be removed. Make sure " +
            "that variables and method headers only have a maximum of one of each type of modifier.";
    }
    else if (err.includes("reference") && err.includes("is ambiguous")) {
        errInfo = "This error occurs when there are multiple imported classes with the same name and you are attempting " +
            "to use one of the conflicting classes. For example, if you import java.util.* and java.awt.* then you will " +
            "get the List classes from both. Attempting to use a List object will result in an error because the program " +
            "doesn't know which List class you are referring to. The best thing to do is make sure you import only the " +
            "classes you are going to use, instead of using '.*' to import all classes from a package. The compiler will " +
            "tell you which classes are conflicting.";
    }
    else if (err.includes("repeated modifier")) {
        errInfo = "This error occurs if you have written the same modifier twice. Remove one of the problematic " +
            "modifiers.";
    }
    else if (err.includes("unclosed string literal")) {
        errInfo = "This error occurs when you forget to put a close quotation mark for a string. The compiler " +
            "detected that you put an open quote for a string, but not a close quote. It is also possible that " +
            "you put a close quote and forgot to put an open quote. Check the line where the compiler says there " +
            "was an error and see if you forgot an open or close quote and add the appropriate one to make sure " +
            "the string is enclosed in quotes.";
    }
    else if (err.includes("modifier") && err.includes("not allowed")) {
        errInfo = "This error occurs when you attempt to put an illegal modifier for a variable, method, etc. Remove " +
            "modifier that the compiler says is illegal. An example of an illegal modifier would be putting 'private' " +
            "as a modifier for a class.";
    }
    else if (errArr[0].includes("Main method is not static")) {
        errInfo = "This error occurs when the main method is not static. Make sure that the static keyword is added. " +
            "The compiler will tell you the format it expects.";
    }
    else if (errArr[0].includes("Main method not found")) {
        errInfo = "This error occurs when the main method is either not created or is not public. Make sure that the " +
            "class has a main method if you wish to run it and that the main method is public.";
    }
    return errInfo;
}